package com.hky.algorithm.realize;

import com.hky.algorithm.mahjongGame.Card;
import com.hky.algorithm.mahjongGame.GameData;
import com.hky.algorithm.mahjongGame.GamePlayer;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.*;

/**
 * 计算危险牌对局数据
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Game {
    // 玩家(对手们）
    public Player[] players;

    // 牌
    public Term[] terms;

    /**
     * 初始化玩家
     *
     * @param gameData   对局数据
     * @param gamePlayer 对局玩家
     */
    public void initPlayers(GameData gameData, GamePlayer gamePlayer) {
        List<GamePlayer> gamePlayers = gameData.players;

        players = new Player[gamePlayers.size() - 1];
        int i = 0;
        for (GamePlayer player : gamePlayers) {
            if (gamePlayer.equals(player)) continue;
            players[i++] = player.selfGame.players[0];
        }
    }

    /**
     * 设置terms到开始状态
     *
     * @param gamePlayer 对局数据
     */
    public void initTerms(GamePlayer gamePlayer) {
        for (Term term : terms) {
            Arrays.fill(term.danger, 0);
            Arrays.fill(term.cards, 4);
            term.cards[0] = 0;
        }
    }

    /**
     * 出现一张可见牌，在不可见牌集合中减去它
     *
     * @param card 对局中新出现的牌
     * @param num  减少个数
     */
    public void subCardToTerm(Card card, int num) {
        terms[card.type.ordinal()].cards[card.num] -= num;
    }

    /**
     * 添加一个card到具体term中
     *
     * @param card 要添加的牌
     * @param num  添加的张数
     */
    public void addCardToTerm(Card card, int num) {
        terms[card.type.ordinal()].cards[card.num] += num;
    }

    /**
     * 获取初始化的Game类，只初始化了Terms，没有初始化players因为不清楚是多少个玩家
     * <br/>
     * Game中terms数组的每一个term是按照Type.ordinal顺序排序的，方便进行增删操作
     *
     * @return 初始化的Game类
     */
    public static Game getInitGame() {
        Game game = new Game();
        game.terms = new Term[3];
        game.terms[Type.TONG.ordinal()] = new Term(new int[10], Type.TONG);
        game.terms[Type.TIAO.ordinal()] = new Term(new int[10], Type.TIAO);
        game.terms[Type.WAN.ordinal()] = new Term(new int[10], Type.WAN);

        return game;
    }

    /**
     * 一个人胡牌，包含万和筒共13张
     */
    public static Game buildGame0() {
        Game game = new Game();
        game.players = new Player[]{
                new Player(13, false, Type.TONG)};

        game.terms = new Term[]{
                new Term(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Type.TONG),
                new Term(new int[]{0, 0, 0, 3, 1, 2, 2, 1, 0, 0}, Type.WAN),
                new Term(new int[]{0, 0, 0, 1, 1, 1, 1, 0, 0, 0}, Type.TIAO)};

        return game;
    }

    /**
     * 筒清龙七对
     */
    public static Game buildGame1() {
        Game game = new Game();
        game.players = new Player[]{
                new Player(13, false, Type.TIAO)};

        game.terms = new Term[]{
                new Term(new int[]{0, 0, 4, 2, 2, 2, 2, 1, 0, 0}, Type.TONG),
                new Term(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Type.WAN),
                new Term(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Type.TIAO)};

        return game;
    }

    /**
     * 筒清一色
     * new Term(new int[]{0, 3, 1, 1, 1, 2, 2, 2, 1, 0}, Type.TONG),
     * new Term(new int[]{0, 0, 3, 0, 2, 1, 1, 3, 4, 2}, Type.WAN),
     * new Term(new int[]{0, 2, 2, 1, 1, 1, 0, 1, 1, 1}, Type.TIAO)
     */
    public static Game buildGame2() {
        Game game = new Game();
        game.players = new Player[]{
                new Player(13, false, Type.WAN)};

        game.terms = new Term[]{
                new Term(new int[]{0, 3, 1, 1, 1, 2, 2, 2, 1, 0}, Type.TONG),
                new Term(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Type.WAN),
                new Term(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Type.TIAO)};

        return game;
    }

    /**
     * 对局一，4个玩家，两个清一色，本家摸了2万
     */
    public static Game buildGame3() {
        Game game = new Game();
        game.players = new Player[]{
                new Player(13, false, Type.WAN),
                new Player(13, false, Type.TONG),
                new Player(13, false, Type.TIAO)};

        game.terms = new Term[]{
                new Term(new int[]{0, 3, 1, 1, 1, 2, 2, 2, 1, 0}, Type.TONG),
                new Term(new int[]{0, 0, 3, 0, 2, 1, 1, 3, 4, 2}, Type.WAN),
                new Term(new int[]{0, 2, 2, 1, 1, 1, 0, 1, 1, 1}, Type.TIAO)};

        return game;
    }

    public static Game buildGame4() {
        Game game = new Game();
        game.players = new Player[]{
                new Player(13, false, Type.TIAO)};

        game.terms = new Term[]{
                new Term(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Type.TONG),
                new Term(new int[]{0, 0, 3, 0, 2, 0, 0, 2, 4, 2}, Type.WAN),
                new Term(new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Type.TIAO)};

        return game;
    }

    /**
     * 清空game所有属性
     */
    public void clear() {
        for (Term term : terms) {
            Arrays.fill(term.cards, 0);
            Arrays.fill(term.danger, 0);
        }
    }

    /**
     * 收集危险牌
     */
    public Set<Card> collectDanger() {
        Set<Card> dangerSet = new HashSet<>();

        for (Term term : terms) {
            int[] dangers = term.danger;
            for (int i = 1; i < dangers.length; i++) {
                if (dangers[i] != 0) dangerSet.add(new Card(i, term.type));
            }
        }
        return dangerSet;
    }

    /**
     * 判断card是不是危险牌
     *
     * @param card 牌
     */
    public boolean isDangerCard(Card card) {
        return terms[card.type.ordinal()].danger[card.num] > 0;
    }
}
